/******************************************************************************/
/* File: tcpTrafficRecver.cpp                                                 */
/******************************************************************************/

#include "tcpTrafficRecver.h"

TCPTrafficRecver::TCPTrafficRecver(TCPSocket *pts, ThreadConf *ptc) 
                : pTcpSock(pts), pThreadConf(ptc) {
    pRecvBuf = new char[DataStore::generalSetting.iTCPBufferLength];
}

TCPTrafficRecver::~TCPTrafficRecver() {
    
    if(pRecvBuf) {
        delete pRecvBuf;
        pRecvBuf = NULL;
    }
}

void TCPTrafficRecver::ExitCleanUp() {
    pThreadConf->SetStoppedFlag(1);
}

void TCPTrafficRecver::Run() {
    
    std::cout << "Running tcp traffic receiver instance....\n";
    
    int updateInterval = DataStore::generalSetting.iUpdateInterval;
    int reportInterval = DataStore::generalSetting.iReportInterval;
    int numOnce = DataStore::generalSetting.iNumOnce;
    int length = DataStore::generalSetting.iTCPBufferLength;
    
    /*
    // 设置接收超时标志，以妨一直阻塞在recv上
    struct timeval recvTimeout;
    recvTimeout.tv_sec = 0;
    recvTimeout.tv_usec = updateInterval;
    
    try {
        pTcpSock->SetSockOpt(SOL_SOCKET, SO_RCVTIMEO, (char *)&recvTimeout, sizeof(recvTimeout));
    } 
    catch (SocketException se) {
        se.PrintException();
        ExitCleanUp();
        return;
    }
    */

    double startTime = 0.0;
    double endTime = 0.0;
    double bandwidth = 0.0;
    
    int64_t totBytes = 0, curBytes = 0;
    struct timeval lastReportTime, nowTime, reportTime;
    
    gettimeofday(&nowTime, NULL);
    
    lastReportTime = nowTime;
    reportTime = nowTime;
    UtilClass::TimevalAddLong(&reportTime, reportInterval);
    
    pThreadConf->SetStartedFlag(1);
    
    while (true) {
        
        // 检查停止标志 --- 为了更好地解决，可以再做最后一次统计，然后再退出 
        if (pThreadConf->GetHaltFlag() == 1) {
            ExitCleanUp();
            return;
        }
            
        int count = 0;
        while (count < numOnce) {
            try {
                curBytes = pTcpSock->RecvCompleteData(pRecvBuf, length);
                count++;
            } 
            catch (SocketException se) {
                se.PrintException();
                std::cout << "TCP traffic receiver shutdown for remote disconnected.\n";
                ExitCleanUp();
                return;
            }
            totBytes += curBytes;
        }
        
        // 检查是否需要上传统计报告
        gettimeofday(&nowTime, NULL);
        if (UtilClass::TimevalGreaterThan(nowTime, reportTime)) {
            double diffUsecs = UtilClass::TimevalDiff(nowTime, lastReportTime);
            double factIntv = diffUsecs / MILLION;
            endTime += factIntv;
            bandwidth = totBytes / factIntv; 
            UploadReport(startTime, endTime, totBytes, bandwidth);
            
            // 重置数据
            startTime = endTime;
            totBytes = 0;
            bandwidth = 0.0;
            
            // 重新设置reportTime
            reportTime = nowTime;
            UtilClass::TimevalAddLong(&reportTime, reportInterval);
            lastReportTime = nowTime;
        }
        
    }
}

void TCPTrafficRecver::UploadReport(double begin, double end, int64_t transfer, double bandwidth) {
    
    std::cout << "Recver upload tcp report...\n";
    
    TcpReport *ptr = new TcpReport();
    ptr->fBeginTime = begin;
    ptr->fEndTime = end;
    ptr->fInterval = end - begin;
    ptr->iTransfer = transfer;
    ptr->fBandwidth = bandwidth;

    Report *pr = new Report();
    pr->iRole = 2;  // -- Recver
    pr->iProto = 1; // -- TCP
    char *rip = pTcpSock->RemoteHostName();
    pr->sSenderIP = strdup(rip);
    pr->iSenderPort = pTcpSock->RemotePortNumber();
    char *lip = pTcpSock->LocalHostName();
    pr->sRecverIP = strdup(lip);
    pr->iRecverPort = pTcpSock->LocalPortNumber();
    pr->pTcpReport = ptr;

    Message *pm = new Message();
    pm->iMessageType = 3;
    pm->pReport = pr;
    
    pThreadConf->pMQ->PushMessage(pm);
}

/******************************************************************************/
/* End File: tcpTrafficRecver.cpp                                             */
/******************************************************************************/